package com.atguigu.srb.core.service.impl;

import com.atguigu.srb.core.hfb.FormHelper;
import com.atguigu.srb.core.hfb.HfbConst;
import com.atguigu.srb.core.hfb.RequestHelper;
import com.atguigu.srb.core.mapper.LendMapper;
import com.atguigu.srb.core.pojo.entity.*;
import com.atguigu.srb.core.pojo.vo.BorrowerApprovalVO;
import com.atguigu.srb.core.pojo.vo.LendDetailVO;
import com.atguigu.srb.core.pojo.vo.LendSearchVO;
import com.atguigu.srb.core.service.*;
import com.atguigu.srb.core.util.*;
import com.atguigu.srb.result.ResponseEnum;
import com.atguigu.srb.util.SrbAssert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * <p>
 * 标的准备表 服务实现类
 * </p>
 *
 * @author Atguigu
 * @since 2024-04-15
 */
@Service
public class LendServiceImpl extends ServiceImpl<LendMapper, Lend> implements LendService {
    @Resource
    private DictService dictService;
    @Resource
    private BorrowerService borrowerService;
    @Resource
    private UserInfoService userInfoService;
    @Resource
    private UserAccountService userAccountService;
    @Resource
    private TransFlowService transFlowService;
    @Resource
    private LendItemService lendItemService;
    @Override
    public List<Lend> getLendList() {
        List<Lend> list = this.list();
        list.forEach(lend -> {
            setParams2Lend(lend);
        });
        return list;
    }

    private void setParams2Lend(Lend lend) {
        Map<String, String> params = new HashMap<>();
        BigDecimal lendYearRate = lend.getLendYearRate();
        BigDecimal serviceRate = lend.getServiceRate();
        params.put("lendYearRate", lendYearRate + "%");
        params.put("serviceRate", serviceRate + "%");
        String returnMethod = dictService.getNameByDictCodeAndValue("returnMethod", lend.getReturnMethod());
        params.put("returnMethod", returnMethod);
        String status = getStatus(lend);
        params.put("status", status);
        lend.setParams(params);
    }

    @Override
    public LendDetailVO getLendDetailById(Long lendId) {
        LendDetailVO lendDetailVO = new LendDetailVO();
        // 查询标的信息 Lend
        Lend lend = this.getById(lendId);
        this.setParams2Lend(lend);
        lendDetailVO.setLend(lend);
        // 查询借款人信息 BorrowerApprovalVO
        Borrower borrower = borrowerService.getOne(Wrappers.lambdaQuery(Borrower.class).eq(Borrower::getUserId, lend.getUserId()));
        BorrowerApprovalVO borrowerApprovalVO = borrowerService.approvalInfo(borrower.getId());
        lendDetailVO.setBorrowerApprovalVO(borrowerApprovalVO);
        return lendDetailVO;
    }

    @Override
    public Page<Lend> getLendListWithCondition(LendSearchVO lendSearchVO, Integer pageNum, Integer pageSize) {
        Page<Lend> page = new Page<>(pageNum, pageSize);
        QueryWrapper<Lend> queryWrapper = new QueryWrapper<>();
        //条件较多，单个类型的条件可以多选
        //标的类型： 1-车易贷,2-房产贷,3-赎楼贷,4-债权贷，5-美容贷
        //年利率： 1-12%以内，2-12%(包含)~14%,3-14%(包含)~16%,4-16%(包含)以上
        //期限：1-1月以下，2-1(包含)~3个月 ，3-3(包含)~6个月，4-6(包含)~12个月，5-12(包含)个月以上
        //还款方式：1-等额本息，2-等额本金，3-到期还本付息，4-按月付息，到期还本

        List<Integer> typeList = lendSearchVO.getTypeList();
        if (!CollectionUtils.isEmpty(typeList)) {
            queryWrapper.and(qw -> {
                typeList.forEach(type -> {
                    String lendYearRate = "";
                    switch (type) {
                        case 1:
                            lendYearRate = "车易贷";
                            break;
                        case 2:
                            lendYearRate = "房产贷";
                            break;
                        case 3:
                            lendYearRate = "赎楼贷";
                            break;
                        case 4:
                            lendYearRate = "债权贷";
                            break;
                        case 5:
                            lendYearRate = "美容贷";
                            break;
                    }
                    qw.or().like("title", lendYearRate);
                });
            });
        }
        List<Integer> lendYearRateList = lendSearchVO.getLendYearRateList();
        if (!CollectionUtils.isEmpty(lendYearRateList)) {
            queryWrapper.and(qw -> {
                lendYearRateList.forEach(lendYearRate -> {
                    switch (lendYearRate) {
                        case 1:
                            qw.or().lt("lend_year_rate", 12);
                            break;
                        case 2:
                            qw.or().between("lend_year_rate", 12, 14);
                            break;
                        case 3:
                            qw.or().between("lend_year_rate", 14, 16);
                            break;
                        case 4:
                            qw.or().ge("lend_year_rate", 16);
                            break;
                    }
                });
            });
        }
        List<Integer> periodList = lendSearchVO.getPeriodList();
        if (!CollectionUtils.isEmpty(periodList)) {
            queryWrapper.and(qw -> {
                periodList.forEach(period -> {
                    switch (period) {
                        case 1:
                            qw.or().lt("period", 1);
                            break;
                        case 2:
                            qw.or().between("period", 1, 3);
                            break;
                        case 3:
                            qw.or().between("period", 3, 6);
                            break;
                        case 4:
                            qw.or().between("period", 6, 12);
                            break;
                        case 5:
                            qw.or().ge("period", 12);
                            break;
                    }
                });
            });
        }
        List<Integer> returnMethodList = lendSearchVO.getReturnMethodList();
        if (!CollectionUtils.isEmpty(returnMethodList)) {
            queryWrapper.and(qw -> {
                returnMethodList.forEach(returnMethod -> {
                    qw.or().eq("return_method", returnMethod);
                });
            });
        }
        queryWrapper.notIn("status", 0, -1);  //不能查询到待发布和已撤标的 标的
        queryWrapper.orderByDesc("publish_date");
        this.page(page, queryWrapper);
        page.getRecords().forEach(lend -> {
            this.setParams2Lend(lend);
        });
        return page;
    }

    @Override
    public BigDecimal getIncome(BigDecimal amount, BigDecimal yearRate, Integer period, Integer returnMethod) {
        BigDecimal interestCount = new BigDecimal(0);
        yearRate = yearRate.divide(new BigDecimal(100),5, RoundingMode.DOWN);
        switch (returnMethod) {
            case 1:
                interestCount = Amount1Helper.getInterestCount(amount, yearRate, period);
                break;
            case 2:
                interestCount = Amount2Helper.getInterestCount(amount, yearRate, period);
                break;
            case 3:
                interestCount = Amount3Helper.getInterestCount(amount, yearRate, period);
                break;
            case 4:
                interestCount = Amount4Helper.getInterestCount(amount, yearRate, period);
                break;
        }
        return interestCount;
    }

    @Override
    public String invest(String token, BigDecimal investAmount, Long lendId) {
        UserInfo userInfo = userInfoService.checkUserBaseInfo(token);
        // 1. 检查用户账号状态
        SrbAssert.assertTrue(userInfo!=null, ResponseEnum.WEIXIN_FETCH_USERINFO_ERROR);
        // 2. 检查投资金额
        Lend lend = this.getById(lendId);
        // 投资金额是否大于最低投资金额
        SrbAssert.assertTrue(investAmount.compareTo(lend.getLowestAmount())>=0);
        // 投资金额是否小于等于自己的余额
        BigDecimal balance = userAccountService.getBalance(userInfo.getId());
        SrbAssert.assertTrue(investAmount.compareTo(balance) <= 0);
        // 该标的是否还可以投资这么金额
        SrbAssert.assertTrue(lend.getAmount().compareTo(lend.getInvestAmount().add(investAmount))>=0);
        // 3. 生成交易日志
        TransFlow transFlow = new TransFlow();
        transFlow.setIsUsed(0);
        transFlow.setTransAmount(investAmount);
        String lendItemNo = LendNoUtils.getLendItemNo();
        transFlow.setTransNo(lendItemNo);
        transFlow.setTransType(3);
        transFlow.setTransTypeName("投资");
        transFlow.setUserId(userInfo.getId());
        transFlow.setUserName(userInfo.getName());
        transFlowService.save(transFlow);
        // 4. 生成投资记录
        LendItem lendItem = new LendItem();
        lendItem.setExpectAmount(this.getIncome(investAmount,lend.getLendYearRate(),lend.getPeriod(),lend.getReturnMethod()));
        lendItem.setInvestAmount(investAmount);
        lendItem.setInvestName(userInfo.getName());
        lendItem.setInvestTime(new Date());
        lendItem.setInvestUserId(userInfo.getId());
        lendItem.setLendEndDate(lend.getLendEndDate());
        lendItem.setLendId(lendId);
        lendItem.setLendItemNo(lendItemNo);
        lendItem.setLendStartDate(lend.getLendStartDate());
        lendItem.setLendYearRate(lend.getLendYearRate());
        lendItem.setRealAmount(new BigDecimal(0));
        lendItem.setStatus(0);
        lendItemService.save(lendItem);
        // 5. 生成自动提交的表单
        Map<String, Object> map = new HashMap<>();
        map.put("agentId",HfbConst.AGENT_ID);
        map.put("voteBindCode",userInfo.getBindCode());
        Long userId = lend.getUserId(); // 借款人的userId
        map.put("benefitBindCode",userInfoService.getById(userId).getBindCode());
        map.put("agentProjectCode",lend.getId());
        map.put("agentProjectName",lend.getTitle());
        map.put("agentBillNo",lendItemNo);
        map.put("voteAmt",investAmount);
//        map.put("votePrizeAmt",);
        map.put("voteFeeAmt",0);
        map.put("projectAmt",lend.getAmount());
        map.put("notifyUrl",HfbConst.INVEST_NOTIFY_URL);
        map.put("returnUrl",HfbConst.INVEST_RETURN_URL);
        map.put("timestamp",System.currentTimeMillis());
        map.put("sign", RequestHelper.getSign(map));
        String form = FormHelper.buildForm(HfbConst.INVEST_URL, map);
        return form;
    }

    @Override
    public void updateLendInvestAmountAndNumber(String lendId, BigDecimal voteAmt) {
        baseMapper.updateLendInvestAmountAndNumber(lendId,voteAmt);
    }

    private static String getStatus(Lend lend) {
        String status = "";
        switch (lend.getStatus()) {
            case 0:
                status = "待发布";
                break;
            case 1:
                status = "募资中";
                break;
            case 2:
                status = "还款中";
                break;
            case 3:
                status = "已结清";
                break;
            case 4:
                status = "结标";
                break;
            case -1:
                status = "已撤标";
                break;
        }
        return status;
    }
}
